package cn.edu.mju.auth.config;


import cn.edu.mju.auth.filter.LoginFilter;
import cn.edu.mju.auth.handler.MyLogoutSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 16423
 */
@Configuration
@EnableWebSecurity
@Order(20)

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    //登录成功拦截器
    private final AuthenticationSuccessHandler authenticationSuccessHandler;

    //登录失败拦截器
    private final AuthenticationFailureHandler authenticationFailureHandler;

    //设置 用户源
    private final UserDetailsService userDetailsService;

    //redis操作工具
    private final RedisTemplate<String,Object> redisTemplate;

    @Autowired
    public WebSecurityConfig(
            AuthenticationSuccessHandler authenticationSuccessHandler,
            AuthenticationFailureHandler authenticationFailureHandler,
            UserDetailsService sysUserDetailsService, RedisTemplate<String, Object> redisTemplate) {

        this.authenticationSuccessHandler = authenticationSuccessHandler;
        this.authenticationFailureHandler = authenticationFailureHandler;
        this.userDetailsService = sysUserDetailsService;
        this.redisTemplate = redisTemplate;
    }


    //密码编码器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }


    //配置自定义UsernamePasswordAuthenticationFilter
    @Bean
    public LoginFilter loginFilter() throws Exception {
        LoginFilter loginFilter = new LoginFilter();
        loginFilter.setUsernameParameter("username");
        loginFilter.setPasswordParameter("password");
        loginFilter.setFilterProcessesUrl("/doLogin");
        loginFilter.setAuthenticationManager(authenticationManager());
        loginFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
        loginFilter.setAuthenticationFailureHandler(authenticationFailureHandler);

        return loginFilter;
    }

    //配置用户源
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    //配置Security
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //开启表单认证
                .formLogin()
                //关闭csrf跨域攻击
                .and().csrf().disable()
                .authorizeRequests()
                .antMatchers("/getCaptcha","/send-mail","/oauth/token").permitAll()

                .anyRequest().authenticated().and()
                //将自定义filter替换默认UsernamePasswordAuthenticationFilter.
                .addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class)

                //添加退出登录操作过滤器
                .addFilterBefore(new OncePerRequestFilter() {
                    @Override
                    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

                        //判断是否携带jwt
                        String fullToken = request.getHeader("Authorization");
                        if (fullToken == null){
                            filterChain.doFilter(request,response);
                            return;
                        }

                        //判断是否为退出登录请求
                        if ("/sso/logout".equals(request.getRequestURI())){
                            //分离Bearer 与 jwt数据
                            String authorization = fullToken.split(" ")[1];
                            System.out.println("------"+authorization);

                            //修改redis中的jwt的值
                            redisTemplate.opsForValue().set(authorization,"false");

                            //测试
                            String  o = (String) redisTemplate.opsForValue().get(authorization);
                            System.out.println(o+" is delete");
                        }
                        //放行
                        filterChain.doFilter(request,response);
                    }
                }, LogoutFilter.class)
                //设置登出url
                .logout().logoutUrl("/logout")
                //设置登出成功过滤器
                .logoutSuccessHandler(new MyLogoutSuccessHandler());
    }

    //将AuthenticationManager交给spring容器
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }



}
